package avicit.bdp.dgs.metadata.compare.util;

import avicit.bdp.dgs.metadata.compare.pojo.CompareReporter;
import avicit.bdp.dgs.metadata.compare.pojo.MetadataTableChange;
import avicit.bdp.dgs.metadata.compare.pojo.MetadataTableDiffItem;
import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Supplier;
import java.util.stream.Collector;
import org.apache.commons.collections4.ListUtils;

public class DBCompareCollector
    implements Collector<MetadataTableChange, CompareReporter, CompareReporter> {

  /** 初始化聚合器 */
  @Override
  public Supplier<CompareReporter> supplier() {
    return CompareReporter::new;
  }

  /** 聚合计算 */
  @Override
  public BiConsumer<CompareReporter, MetadataTableChange> accumulator() {
    return (reporter, change) -> {
      reporter.setTotalCount(reporter.getTotalCount() + 1);

      if (MetadataTableDiffItem.CREATE.equals(change.getTableDiff().getType())) {
        reporter.setAddCount(reporter.getAddCount() + 1);
        reporter.getAddList().add(change.getTable().getName());
      } else if (MetadataTableDiffItem.ALTER.equals(change.getTableDiff().getType())) {
        reporter.setAlterCount(reporter.getAlterCount() + 1);
        reporter.getAlterList().add(change.getTable().getName());
      } else if (MetadataTableDiffItem.DROP.equals(change.getTableDiff().getType())) {
        reporter.setDropCount(reporter.getDropCount() + 1);
        reporter.getDropList().add(change.getTable().getName());
      }
    };
  }

  /** 多流结果合并 */
  @Override
  public BinaryOperator<CompareReporter> combiner() {
    return (r1, r2) -> {
      CompareReporter r3 = new CompareReporter();
      r3.setTotalCount(r1.getTotalCount() + r2.getTotalCount());

      r3.setAddCount(r1.getAddCount() + r2.getAddCount());
      r3.setAddList(ListUtils.union(r1.getAddList(), r2.getAddList()));

      r3.setAlterCount(r1.getAlterCount() + r2.getAlterCount());
      r3.setAlterList(ListUtils.union(r1.getAlterList(), r2.getAlterList()));

      r3.setDropCount(r1.getDropCount() + r2.getDropCount());
      r3.setDropList(ListUtils.union(r1.getDropList(), r2.getDropList()));
      return r3;
    };
  }

  @Override
  public Function<CompareReporter, CompareReporter> finisher() {
    return Function.identity();
  }

  @Override
  public Set<Characteristics> characteristics() {
    return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
  }
}
